<?php
/**
 * @file WCSearchContainer.php
 * @author Alejandro Dario Simi
 * @date $Date: 2013-03-06 02:33:47 +0000 (Wed, 06 Mar 2013) $
 *
 * $Id: WCSearchContainer.php 58 2013-03-06 02:33:47Z daemonraco@gmail.com $
 * $URL: http://wcomix.googlecode.com/svn/tags/wcomix-1.0-BETA1/includes/search/WCSearchContainer.php $
 */

/**
 * @class WCSearchContainer
 */
class WCSearchContainer {
	protected 	$_gid		= false;
	protected 	$_items		= array();
	protected	$_itemsByType	= array();
	protected 	$_itemsCount	= 0;
	protected 	$_sorted	= true;
	protected	$_words		= array();

	public function __construct() {
	}
	public function __destruct() {
	}

	//
	// Public methods
	public function addCollection($collectionId, $groupId, $word=false, $exact=false, $parent=false) {
		return $this->addItem("CL", $collectionId, $groupId, $word, $exact, $parent);
	}
	public function addComic($comicId, $groupId, $word=false, $exact=false, $parent=false) {
		return $this->addItem("CX", $comicId, $groupId, $word, $exact, $parent);
	}
	public function addDirectory($directoryId, $groupId, $word=false, $exact=false, $parent=false) {
		return $this->addItem("DI", $directoryId, $groupId, $word, $exact, $parent);
	}
	public function addItem($type, $itemId, $groupId, $word=false, $exact=false, $parent=false) {
		$added = false;

		$this->_sorted = false;

		if($this->_gid === false) {
			$this->_gid = $groupId;
		}

		if(!isset($this->_itemsByType[$type])) {
			$this->_itemsByType[$type] = array();
		}
		if(!in_array($itemId, $this->_itemsByType[$type])) {
			$this->_itemsByType[$type][] = $itemId;
		}

		$id = $groupId.$type.$itemId;
		if(!isset($this->_items[$id])) {
			$this->_items[$id] = array(
					"factors"	=> array(
							"hits"		=> 0,
							"type"		=> WCSearchFactory::$TypePriority[$type],
							"e-words"	=> 0,
							"p-words"	=> 0
					),
					"type"		=> $type,
					"id"		=> $itemId,
					"group"		=> $groupId,
					"words"		=> array(
							"exact"		=> array(),
							"partial"	=> array()
					)
			);

			$this->_itemsCount++;
			$added = true;
		}
		$this->_items[$id]["factors"]["hits"]++;

		if($word) {
			$auxName = $exact ? "exact" : "partial";
			if(!isset($this->_items[$id]["words"][$auxName][$word])) {
				$this->_items[$id]["words"][$auxName][$word] = 0;
			}
			$this->_items[$id]["words"][$auxName][$word]++;
		}

		if($parent) {
			foreach(array("exact","partial") as $match) {
				foreach($parent["words"][$match] as $word => $hits) {
					if(!isset($this->_items[$id]["words"][$match][$word])) {
						$this->_items[$id]["words"][$match][$word] = 0;
					}
					$this->_items[$id]["words"][$match][$word] += $hits;
				}
			}
		}

		return $added;
	}
	public function addRule($ruleId, $groupId, $word=false, $exact=false, $parent=false) {
		return $this->addItem("RL", $ruleId, $groupId, $word, $exact, $parent);
	}
	public function addTag($tagId, $groupId, $word=false, $exact=false, $parent=false) {
		return $this->addItem("TA", $tagId, $groupId, $word, $exact, $parent);
	}
	public function count() {
		return $this->_itemsCount;
	}
	public function filter(WCSearchContainer &$minus) {
		foreach($minus->_items as $id => $item) {
			if(isset($this->_items[$id])) {
				unset($this->_items[$id]);
			}
		}
		return $this->_itemsCount = count($this->_items);
	}
	public function gid() {
		return $this->_gid;
	}
	public function item($type, $itemId, $groupId) {
		$id = $groupId.$type.$itemId;
		return isset($this->_items[$id]) ? $this->_items[$id] : false;
	}
	public function items() {
		$this->sort();
		return $this->_items;
	}
	public function setWords(&$words) {
		$this->_words = $words;
	}
	public function typeIds($type) {
		return isset($this->_itemsByType[$type]) ? $this->_itemsByType[$type] : array();
	}

	//
	// Protected methods
	protected function calculateFactors() {
		foreach($this->_items as $id => $item) {
			$factor = 0;
			foreach($item["words"]["exact"] as $word => $hits) {
				$factor += $hits;
				//$factor += $hits * strlen($word);
			}
			$this->_items[$id]["factors"]["e-words"] = $factor;

			$factor = 0;
			foreach($item["words"]["partial"] as $word => $hits) {
				$factor += $hits;
				//$factor += $hits * strlen($word);
			}
			$this->_items[$id]["factors"]["p-words"] = $factor;
		}
	}
	protected function sort() {
		if(!$this->_sorted) {
			$this->calculateFactors();
			uasort($this->_items, 'WCSearchContainer::Compare');
			$this->_sorted = true;
		}
	}

	//
	// Public class methods.
	public static function Compare(&$a, &$b) {
		$out	= 0;

		$aFactors = $a["factors"];
		$bFactors = $b["factors"];

		if($aFactors["e-words"] != $bFactors["e-words"]) {
			$out = $aFactors["e-words"] > $bFactors["e-words"] ? -1 : 1;
		} elseif($aFactors["p-words"] != $bFactors["p-words"]) {
			$out = $aFactors["p-words"] > $bFactors["p-words"] ? -1 : 1;
		} elseif($aFactors["hits"] != $bFactors["hits"]) {
			$out = $aFactors["hits"] > $bFactors["hits"] ? -1 : 1;
		} elseif($aFactors["type"] != $bFactors["type"]) {
			$out = $aFactors["type"] > $bFactors["type"] ? -1 : 1;
		}

		return $out;
	}
}

?>
